﻿using CSharp.Study.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using static CSharp.Study.ExpTest.ExpData;

namespace CSharp.Study.ExpTest
{
    public class ExpDemo
    {
        public static void Go()
        {

            //Demo2();
            Expression<Func<User, string>> exp = SelectTableKeysExpression<User>();

            Expression<Func<User, string>> exp2 = x => x.Name;

            var list = User.Users.Select(x => x.Name).ToList();
        }

        public static void Demo1()
        {
            /*
            var books = Books;
            Expression<Func<Book, bool>> exp = x => x.Price > 10;
            ConstantExpression 常量1 = Expression.Constant(1);//1
            BinaryExpression 逻辑1 = Expression.GreaterThan(Expression.Constant(2), Expression.Constant(1));//2>1;
            ParameterExpression 参数1 = Expression.Parameter(typeof(Book), "x");


            var one = Expression.Constant(1, typeof(int));
            var two = Expression.Constant(2, typeof(int));
            var add = Expression.Add(one, two);
            */

            ParameterExpression param = Expression.Parameter(typeof(string), "x");
            Expression exp1 = Expression.Constant(1);
            MethodCallExpression methodCall = Expression.Call(
                typeof(Console).GetMethod(nameof(Console.WriteLine),
                new Type[] { typeof(string) })!, Expression.Constant("aaa"));

            string x = methodCall.ToString();

            string[] list = new string[] { "aaa", "bbb" };
            string dasd = string.Join(',', list);

            MethodCallExpression joinExp = Expression.Call(
                typeof(string).GetMethod(nameof(string.Join),
                new Type[] { typeof(char), typeof(string[]) })!,
                Expression.Constant(','), Expression.Constant(new string[] { "aaa", "bbb" }));
            Expression<Func<string>> exp = Expression.Lambda<Func<string>>(joinExp, null);
            Func<string> xxx = exp.Compile();
            string a = xxx.Invoke();
            string xx = joinExp.ToString();
        }

        public static void Demo2()
        {
            ParameterExpression para = Expression.Parameter(typeof(User), "x");
            List<Expression> expProperties = new List<Expression>();
            expProperties.Add(
                    Expression.Call(Expression.Convert(
                    Expression.MakeMemberAccess(para, typeof(User).GetProperty(nameof(User.Id))!), typeof(object)),
                    typeof(object).GetMethod(nameof(object.ToString))!)

                );
            expProperties.Add(
                     Expression.Call(Expression.Convert(
                     Expression.MakeMemberAccess(para, typeof(User).GetProperty(nameof(User.Name))!), typeof(object)),
                     typeof(object).GetMethod(nameof(object.ToString))!)

                 );
            NewArrayExpression newList = Expression.NewArrayInit(typeof(string), expProperties);
            MethodCallExpression joinExp = Expression.Call(
                typeof(string).GetMethod(nameof(string.Join),
                new Type[] { typeof(char), typeof(string[]) })!,
                Expression.Constant(','), newList);
            Expression<Func<User, string>> exp = Expression.Lambda<Func<User, string>>(joinExp, para);

            string a = exp.ToString();
        }

        public static Expression<Func<T, string>> SelectTableKeysExpression<T>()
        {
            Type type = typeof(T);
            ParameterExpression para = Expression.Parameter(type, "x");
            List<Expression> expProperties = new List<Expression>();
            foreach (PropertyInfo property in type.GetProperties())
            {
                expProperties.Add(
                    Expression.Call(Expression.Convert(
                    Expression.MakeMemberAccess(para, property), typeof(object)
                    ),
                    typeof(object).GetMethod(nameof(object.ToString))!)
                );
            }
            NewArrayExpression newList = Expression.NewArrayInit(typeof(string), expProperties);
            MethodCallExpression joinExp = Expression.Call(
                typeof(string).GetMethod(nameof(string.Join),
                new Type[] { typeof(char), typeof(string[]) })!,
                Expression.Constant(','), newList);
            Expression<Func<T, string>> exp = Expression.Lambda<Func<T, string>>(joinExp, para);
            return exp;
        }
    }
}
